home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #2 / Ham Radio 2000 - Volume 2.iso / HAMV2 / TCP_IP / TNOS230S / ASY.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-09-06  |  11.0 KB  |  459 lines

  1. /* Generic serial line interface routines
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4. /* Mods by G1EMM */
  5. #include "global.h"
  6. #include "commands.h"
  7. #include "proc.h"
  8. #include "iface.h"
  9. #include "slhc.h"
  10. #ifdef UNIX
  11. #include "unixasy.h"
  12. #else
  13. #include "n8250.h"
  14. #endif
  15. #include "asy.h"
  16. #include "kiss.h"
  17. #include "pktdrvr.h"
  18. #include "ppp.h"
  19. #include "slip.h"
  20. #include "nrs.h"
  21. #include "ctype.h"
  22.  
  23. #if !defined(_lint)
  24. static char rcsid[] OPTIONAL = "$Id: asy.c,v 1.20 1997/09/07 00:31:16 root Exp root $";
  25. #endif
  26.  
  27. int SLIP_MAX = _SLIP_MAX;
  28. int ASY_MAX = _ASY_MAX;
  29.  
  30. static int asy_detach (struct iface * ifp);
  31. extern void pasy (struct asy *asyp);
  32.  
  33.  
  34. /* Attach a serial interface to the system
  35.  * argv[0]: hardware type, must be "asy"
  36.  * argv[1]: I/O address, e.g., "0x3f8"
  37.  * argv[2]: vector, e.g., "4"  In hex, 0x prefix optional.
  38.  * argv[3]: mode, may be:
  39.  *        "slip" (point-to-point SLIP)
  40.  *        "ax25" (AX.25 frame format in SLIP for raw TNC)
  41.  *        "nrs" (NET/ROM format serial protocol)
  42.  *        "ppp" (Point-to-Point Protocol, RFC1171, RFC1172)
  43.  *        "pkiss" (Polled KISS ala G8BPQ)
  44.  * argv[4]: interface label, e.g., "sl0"
  45.  * argv[5]: receiver ring buffer size in bytes
  46.  * argv[6]: maximum transmission unit, bytes
  47.  * argv[7]: interface speed, e.g, "9600"
  48.  * argv[8]: optional flags,
  49.  *        'c' BPQ-style checksum used in kiss mode - WG7J
  50.  *        'v' for Van Jacobson TCP header compression (SLIP only,
  51.  *            use ppp command for VJ compression with PPP);
  52.  *        'f' for forced use of the 16550 fifo's - WG7J
  53.  *        'dd' to set 16550 trigger level to 'dd' (an integer) - WG7J
  54.  *        't' to display pkiss outbound polling on trace display
  55.  *            (supressed by default)
  56.  */
  57. int
  58. asy_attach (argc, argv, p)
  59. int argc;
  60. char *argv[];
  61. void *p OPTIONAL;
  62. {
  63. register struct iface *ifp;
  64. struct asy *asyp;
  65. char *ifn;
  66. int dev;
  67. int xdev;
  68. int trigchar = -1;
  69. char monitor = FALSE;
  70. int polled = 0;
  71. int triglevel = 0;
  72. int force = 0;
  73. char *cp;
  74. #if    defined(SLIP) || defined(AX25)
  75. struct slip *sp = (struct slip *)0;
  76. #endif
  77. #ifdef    NRS
  78. struct nrs *np = (struct nrs *)0;
  79. #endif
  80.  
  81.     if (if_lookup (argv[4]) != NULLIF) {
  82.         tprintf (Existingiface, argv[4]);
  83.         return -1;
  84.     }
  85.     /* Find unused asy control block */
  86.     for (dev = 0; dev < ASY_MAX; dev++) {
  87.         asyp = &Asy[dev];
  88.         if (asyp->iface == NULLIF)
  89.             break;
  90.     }
  91.     if (dev >= ASY_MAX) {
  92.         tputs ("Too many async controllers\n");
  93.         return -1;
  94.     }
  95.  
  96.     /* Create interface structure and fill in details */
  97.     ifp = (struct iface *) callocw (1, sizeof (struct iface));
  98.  
  99.     ifp->addr = Ip_addr;
  100.     ifp->name = strdup (argv[4]);
  101.     ifp->iface_metric = 1;
  102.     ifp->mtu = (int16) atoi (argv[6]);
  103.     ifp->dev = dev;
  104.     ifp->stop = asy_detach;
  105.  
  106.     /*Check for forced 16550 fifo usage - WG7J */
  107.     if ((argc > 8) && ((cp = strchr (argv[8], 'f')) != NULLCHAR)) {
  108.         force = 1;
  109.         if ((triglevel = atoi (++cp)) == 0)    /* is there an additional arg ? */
  110.             if (argc > 9)
  111.                 triglevel = atoi (argv[9]);
  112.     }
  113. #ifdef    SLIP
  114.     if (stricmp (argv[3], "SLIP") == 0) {
  115.         for (xdev = 0; xdev < SLIP_MAX; xdev++) {
  116.             sp = &Slip[xdev];
  117.             if (sp->iface == NULLIF)
  118.                 break;
  119.         }
  120.         if (!sp || xdev >= SLIP_MAX) {
  121.             tputs ("Too many slip devices\n");
  122.             free (ifp->name);
  123.             free ((char *) ifp);
  124.             return -1;
  125.         }
  126.         (void) setencap (ifp, "SLIP");
  127.         ifp->ioctl = asy_ioctl;
  128.         ifp->raw = slip_raw;
  129.         ifp->show = slip_status;
  130.         ifp->flags = 0;
  131.         ifp->xdev = xdev;
  132.  
  133.         sp->iface = ifp;
  134.         sp->send = asy_send;
  135.         sp->get = get_asy;
  136.         sp->type = CL_SERIAL_LINE;
  137.         trigchar = FR_END;
  138. #ifdef VJCOMPRESS
  139.         if ((argc > 8) && (strchr (argv[8], 'v') != NULLCHAR)) {
  140.             sp->escaped |= SLIP_VJCOMPR;
  141.             sp->slcomp = slhc_init (16, 16);
  142.         }
  143. #else
  144.         sp->slcomp = NULL;
  145. #endif /* VJCOMPRESS */
  146.         ifp->rxproc = newproc (ifn = if_name (ifp, " rx"), 256, asy_rx, xdev, NULL, NULL, 0);
  147.         free (ifn);
  148.     } else
  149. #endif
  150. #ifdef    AX25
  151.         if (stricmp (argv[3], "AX25") == 0
  152. #ifdef POLLEDKISS
  153.           || stricmp (argv[3], "PKISS") == 0
  154. #endif
  155.           ) {
  156.         /* Set up a SLIP link to use AX.25 */
  157.         for (xdev = 0; xdev < SLIP_MAX; xdev++) {
  158.             sp = &Slip[xdev];
  159.             if (sp->iface == NULLIF)
  160.                 break;
  161.         }
  162.         if (!sp || xdev >= SLIP_MAX) {
  163.             tputs ("Too many ax25"
  164. #ifdef POLLEDKISS
  165.                    "or pkiss"
  166. #endif
  167.                    " devices\n");
  168.             free (ifp->name);
  169.             free ((char *) ifp);
  170.             return -1;
  171.         }
  172.         (void) setencap (ifp, "AX25");
  173. #ifdef KISS
  174.         ifp->ioctl = kiss_ioctl;
  175.         ifp->raw = kiss_raw;
  176. #endif
  177.         ifp->show = slip_status;
  178.         ifp->port = 0;    /* G1EMM */
  179.         if (ifp->hwaddr == NULLCHAR)
  180.             ifp->hwaddr = mallocw (AXALEN);
  181.         memcpy (ifp->hwaddr, Mycall, AXALEN);
  182.         if (ifp->ipcall == NULLCHAR)
  183.             ifp->ipcall = mallocw (AXALEN);
  184.         memcpy (ifp->ipcall, Mycall, AXALEN);
  185.         ifp->xdev = xdev;
  186.  
  187.         sp->iface = ifp;
  188.         sp->send = asy_send;
  189.         sp->kiss[ifp->port] = ifp;    /* G1EMM */
  190.         sp->get = get_asy;
  191.         sp->type = CL_KISS;
  192.         sp->polled = sp->usecrc = sp->tracepoll = 0;
  193.         trigchar = FR_END;
  194.         ifp->rxproc = newproc (ifn = if_name (ifp, " rx"), 256, asy_rx, xdev, NULL, NULL, 0);
  195. #ifdef POLLEDKISS
  196.         if (toupper (*argv[3]) == 'P') {
  197.             polled = 1;
  198.             sp->polled = sp->usecrc = 1;    /* PKISS => usecrc (for compatibility) */
  199.             if ((argc > 8) && strchr (argv[8], 't') != NULLCHAR)
  200.                 sp->tracepoll = 1;
  201.         }
  202.         if ((argc > 8) && (strchr (argv[8], 'c') != NULLCHAR))
  203.             sp->usecrc = 1;
  204. #endif
  205.         free (ifn);
  206.         } else
  207. #endif
  208. #ifdef    NRS
  209.         if (stricmp (argv[3], "NRS") == 0) {
  210.         /* Set up a net/rom serial iface */
  211.         for (xdev = 0; xdev < SLIP_MAX; xdev++) {
  212.             np = &Nrs[xdev];
  213.             if (np->iface == NULLIF)
  214.                 break;
  215.         }
  216.         if (!np || xdev >= SLIP_MAX) {
  217.             tputs ("Too many nrs devices\n");
  218.             free (ifp->name);
  219.             free ((char *) ifp);
  220.             return -1;
  221.         }
  222.         /* no call supplied? */
  223.         (void) setencap (ifp, "AX25");
  224.         ifp->ioctl = asy_ioctl;
  225.         ifp->raw = nrs_raw;
  226.         /*        ifp->show = nrs_status; */
  227.         ifp->hwaddr = mallocw (AXALEN);
  228.         memcpy (ifp->hwaddr, Mycall, AXALEN);
  229.         ifp->ipcall = mallocw (AXALEN);
  230.         memcpy (ifp->ipcall, Mycall, AXALEN);
  231.         ifp->xdev = xdev;
  232.         np->iface = ifp;
  233.         np->send = asy_send;
  234.         np->get = get_asy;
  235.         trigchar = ETX;
  236.         ifp->rxproc = newproc (ifn = if_name (ifp, " nrs"), 256, nrs_recv, xdev, NULL, NULL, 0);
  237.         free (ifn);
  238.         } else
  239. #endif
  240. #ifdef    PPP
  241.         if (stricmp (argv[3], "PPP") == 0) {
  242.         /* Setup for Point-to-Point Protocol */
  243.         trigchar = HDLC_FLAG;
  244.         monitor = TRUE;
  245.         (void) setencap (ifp, "PPP");
  246.         ifp->ioctl = asy_ioctl;
  247.         ifp->flags = FALSE;
  248.         /* Initialize parameters for various PPP phases/protocols */
  249.         if (ppp_init (ifp) != 0) {
  250.             tputs ("Cannot allocate PPP control block\n");
  251.             free (ifp->name);
  252.             free ((char *) ifp);
  253.             return -1;
  254.         }
  255.         } else
  256. #endif /* PPP */
  257.         {
  258.         tprintf ("Mode %s unknown for interface %s\n", argv[3], argv[4]);
  259.         free (ifp->name);
  260.         free ((char *) ifp);
  261.         return -1;
  262.         }
  263.  
  264.     /* Link in the interface */
  265.     ifp->next = Ifaces;
  266.     Ifaces = ifp;
  267. #ifdef UNIX
  268.     /* *ix version can fail (e.g. "device locked"). Detach if it does. */
  269.     if (asy_init (dev, ifp, argv[1], argv[2], (int16) atol (argv[5]),
  270.         trigchar, monitor, (int16) atol (argv[7]), force, triglevel, polled) == -1)
  271.         (void) if_detach (ifp);
  272. #else
  273.     (void) asy_init (dev, ifp, argv[1], argv[2], (int16) atol (argv[5]),
  274.         trigchar, monitor, (int16) atol (argv[7]), force, triglevel, polled);
  275. #endif
  276.     return 0;
  277. }
  278.  
  279.  
  280. static int
  281. asy_detach (ifp)
  282. struct iface *ifp;
  283. {
  284.     (void) asy_stop (ifp);
  285.  
  286. #ifdef    SLIP
  287.     if (stricmp (ifp->iftype->name, "SLIP") == 0) {
  288.         Slip[ifp->xdev].iface = NULLIF;
  289. #ifdef VJCOMPRESS
  290.         slhc_free (Slip[ifp->xdev].slcomp);
  291.         Slip[ifp->xdev].slcomp = NULL;
  292. #endif /* VJCOMPRESS */
  293.     } else
  294. #endif
  295. #ifdef    AX25
  296.     if (stricmp (ifp->iftype->name, "AX25") == 0 && Slip[ifp->xdev].iface == ifp)
  297.         Slip[ifp->xdev].iface = NULLIF;
  298.     else
  299. #endif
  300. #ifdef    NRS
  301.     if (stricmp (ifp->iftype->name, "AX25") == 0 && Nrs[ifp->xdev].iface == ifp) 
  302.         Nrs[ifp->xdev].iface = NULLIF;
  303.     else
  304. #endif
  305. #ifdef    PPP
  306.     if (stricmp (ifp->iftype->name, "PPP") == 0)
  307.         (void) ppp_free (ifp);
  308.     else
  309. #endif
  310.     {
  311.         tprintf ("invalid type %s for interface %s\n", ifp->iftype->name, ifp->name);
  312.         free (ifp->name);
  313.         free (ifp);
  314.         return -1;
  315.     }
  316.     return 0;
  317. }
  318.  
  319.  
  320. /* Execute user comm command */
  321. int
  322. doasycomm (argc, argv, p)
  323. int argc OPTIONAL;
  324. char *argv[];
  325. void *p OPTIONAL;
  326. {
  327. register struct iface *ifp;
  328. register struct asy *ap;
  329. int dev;
  330. struct mbuf *bp;
  331.  
  332.     if ((ifp = if_lookup (argv[1])) == NULLIF) {
  333.         tprintf (Badinterface, argv[1]);
  334.         return 1;
  335.     }
  336.     for (dev = 0, ap = Asy; dev < ASY_MAX; dev++, ap++)
  337.         if (ap->iface == ifp)
  338.             break;
  339.     if (dev == ASY_MAX) {
  340.         tprintf ("Interface %s not asy port\n", argv[1]);
  341.         return 1;
  342.     }
  343.     bp = pushdown (NULLBUF, (int16) strlen (argv[2]) + 2);
  344.     strncpy ((char *)bp->data, argv[2], strlen(argv[2]) + 1);
  345.     strcat ((char *)bp->data, "\r");
  346.     bp->cnt = (int16) (strlen (argv[2]) + 1);
  347.     (void) asy_send (dev, bp);
  348.     return 0;
  349. }
  350.  
  351.  
  352. int
  353. doasystat (int argc, char **argv, void *p OPTIONAL)
  354. {
  355. register struct asy *asyp;
  356. struct iface *ifp;
  357. int i;
  358. int k;
  359.  
  360.     if (argc < 2) {
  361.         for (k = 0, asyp = Asy; k < ASY_MAX; k++, asyp++) {
  362.             if (asyp->iface != NULLIF)
  363.                 pasy (asyp);
  364.         }
  365.         return 0;
  366.     }
  367.     for (i = 1; i < argc; i++) {
  368.         if ((ifp = if_lookup (argv[i])) == NULLIF) {
  369.             tprintf ("Interface %s unknown\n", argv[i]);
  370.             continue;
  371.         }
  372.         for (k = 0, asyp = Asy; k < ASY_MAX; k++, asyp++) {
  373.             if (asyp->iface == ifp) {
  374.                 pasy (asyp);
  375.                 break;
  376.             }
  377.         }
  378.         if (k == ASY_MAX || !asyp)
  379.             tprintf ("Interface %s not asy\n", argv[i]);
  380.     }
  381.  
  382.     return 0;
  383. }
  384.  
  385.  
  386.  
  387. #ifdef KISS
  388.  
  389. /* Attach a pseudo ax25 interface to the system, for local loopback of ax25
  390.  *
  391.  */
  392. int axloop_attach (int argc OPTIONAL, char *argv[] OPTIONAL, void *p OPTIONAL)
  393. {
  394. register struct iface *ifp;
  395. int xdev;
  396. struct slip *sp = (struct slip *)0;
  397.  
  398.     if (if_lookup ("axlp") != NULLIF) {
  399.         tprintf (Existingiface, "axlp");
  400.         return -1;
  401.     }
  402.  
  403.     /* Create interface structure and fill in details */
  404.     ifp = (struct iface *) callocw (1, sizeof (struct iface));
  405.  
  406.     ifp->addr = Ip_addr;
  407.     ifp->name = strdup ("axlp");
  408.     ifp->iface_metric = 1;
  409.     ifp->mtu = 1500;
  410.     ifp->dev = 0;
  411.     ifp->flags = LOOPBACK_AX25;
  412.     ifp->stop = asy_detach;
  413.  
  414.  
  415.     /* Set up a SLIP link to use AX.25 */
  416.     for (xdev = 0; xdev < SLIP_MAX; xdev++) {
  417.         sp = &Slip[xdev];
  418.         if (sp->iface == NULLIF)
  419.             break;
  420.     }
  421.     if (!sp || xdev >= SLIP_MAX) {
  422.         tputs ("Too many ax25"
  423. #ifdef POLLEDKISS
  424.                "or pkiss"
  425. #endif
  426.                " devices\n");
  427.         free (ifp->name);
  428.         free ((char *) ifp);
  429.         return -1;
  430.     }
  431.  
  432.     (void) setencap (ifp, "AX25");
  433.     ifp->ioctl = kiss_ioctl;
  434.     ifp->raw = kiss_raw;
  435.  
  436.     ifp->show = slip_status;
  437.     ifp->port = 0;    /* G1EMM */
  438.     if (ifp->hwaddr == NULLCHAR)
  439.         ifp->hwaddr = mallocw (AXALEN);
  440.     memcpy (ifp->hwaddr, Mycall, AXALEN);
  441.     if (ifp->ipcall == NULLCHAR)
  442.         ifp->ipcall = mallocw (AXALEN);
  443.     memcpy (ifp->ipcall, Mycall, AXALEN);
  444.     ifp->xdev = xdev;
  445.  
  446.     sp->iface = ifp;
  447.     sp->send = asy_send;
  448.     sp->kiss[ifp->port] = ifp;    /* G1EMM */
  449.     sp->get = get_asy;
  450.     sp->type = CL_KISS;
  451.     sp->polled = sp->usecrc = sp->tracepoll = 0;
  452.  
  453.     ifp->next = Ifaces;
  454.     Ifaces = ifp;
  455.     return 0;
  456. }
  457. #endif
  458.  
  459.